package com.ds.infra.rpc.core.proxy;

import com.ds.infra.rpc.core.constant.RpcConstants;
import com.ds.infra.rpc.core.loadbalance.LoadBalance;
import com.ds.infra.rpc.core.protocol.RpcProtocol;
import com.ds.infra.rpc.core.protocol.RpcRequest;
import com.ds.infra.rpc.core.protocol.RpcResponse;
import com.ds.infra.rpc.core.transport.client.RpcClient;
import io.netty.handler.timeout.TimeoutException;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * JDK动态代理处理器
 *
 * @author WeiShaoying
 */
@Slf4j
public class RpcClientProxyHandler implements InvocationHandler {

    // private final ServiceInvoker serviceInvoker;
    private final RpcClient rpcClient;  // 直接依赖RpcClient
    private final String version;
    private final LoadBalance loadBalance;
    private final int timeout;
    private final int retries;

    public RpcClientProxyHandler(RpcClient rpcClient, String version,
                                 LoadBalance loadBalance, int timeout, int retries) {
        this.rpcClient = rpcClient;
        this.version = version;
        this.loadBalance = loadBalance;
        this.timeout = timeout;
        this.retries = retries;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 1. 过滤Object类方法
        if (Object.class.equals(method.getDeclaringClass())) {
            return handleObjectMethod(proxy, method, args);
        }
        // 1. 构建RpcRequest
        RpcRequest request = buildRequest(method, args);
        // 2. 构建完整协议包
        RpcProtocol<RpcRequest> protocol = new RpcProtocol<>(
                new RpcProtocol.Header(
                        RpcConstants.MAGIC, // 显式赋值魔数
                        (byte) 1,       // 版本
                        RpcProtocol.MsgType.REQUEST.getValue(),
                        0              // 长度占位
                ),
                request
        );
        // 3. 发送请求
        // return serviceInvoker.invoke(serviceName, version, request); // TODO：负载均衡逻辑待完善

        CompletableFuture<RpcResponse> future = rpcClient.send(protocol);
        // 4. 处理响应
        try {
            RpcResponse response = future.get(5, TimeUnit.SECONDS); // 添加超时控制
            if (response.isSuccess()) {
                return response.getData();
            } else {
                throw new RuntimeException(response.getErrorMsg());
            }
        } catch (TimeoutException e) {
            throw new RuntimeException("RPC timeout", e);
        } catch (Exception e) {
            throw new RuntimeException("RPC failed", e);
        }
    }

    private RpcRequest buildRequest(Method method, Object[] args) {
        RpcRequest request = new RpcRequest();
        request.setRequestId(UUID.randomUUID().toString());
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameterTypes(method.getParameterTypes());
        request.setParameters(args);
        request.setVersion(version);
        return request;
    }

    private Object handleObjectMethod(Object proxy, Method method, Object[] args) {
        // 处理toString/hashCode等Object方法
        return switch (method.getName()) {
            case "toString" -> "RPC Proxy@" + Integer.toHexString(hashCode());
            case "hashCode" -> hashCode();
            case "equals" -> proxy == args[0];
            default -> throw new UnsupportedOperationException(method.getName());
        };
    }
}
